﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using ORM.Business.Models;
using ORM.Common.Helpers;
using ORM.Business.Interfaces;
using ORM.Business.Models.Entities;
using ORM.Common;
using ORM.Framework.Filters;
using ORM.ViewModels.Guides;
using System.Configuration;
using ORM.Common.Logging;
namespace ORM.Controllers
{
    public class GuideController : OrmControllerBase
    {
        private IGuideRepository _iGuideRepository;
        private IModelRepository _iModelRepository;
        private IDeviceRepository _iDeviceRepository;
        private IManufacturerRepository _iManufacturerRepository;
        private ICommentRepository _iCommentRepository;
        private OrmEntities ORMdb = new OrmEntities();
        public GuideController(IGuideRepository iGuideRepository, IModelRepository iModelRepository, IDeviceRepository iDeviceRepository, IManufacturerRepository iManufacturerRepository, ICommentRepository iCommentRepository)
        {
            _iGuideRepository = iGuideRepository;
            _iModelRepository = iModelRepository;
            _iDeviceRepository = iDeviceRepository;
            _iManufacturerRepository = iManufacturerRepository;
            _iCommentRepository = iCommentRepository;
        }



        //
        // GET: /Guide/

        public ViewResult Index(string condition, int pageNo = 1, int deviceId = 0, int manufacturerId = 0, int modelId = 0, string stringToSearch = "", int guideTypeId = 0)
        {
            List<Guide> guideList = new List<Guide>();
            ViewData["Device_Name"] = new SelectList(ORMdb.Devices.Where(i => !i.IsDeleted), "Id", "Name", null).OrderBy(d => d.Text);
            ViewData["Manufacturer_Name"] = new SelectList(ORMdb.Manufacturers.Where(i => !i.IsDeleted), "Id", "Name", null).OrderBy(m => m.Text);
            ViewData["Model_Name"] = new SelectList(ORMdb.Models.Where(i => !i.IsDeleted && i.DeviceId == deviceId && i.ManufacturerId == manufacturerId), "Id", "Name", null).OrderBy(m => m.Text);
            ViewData["GuideType_Name"] = new SelectList(ORMdb.GuideTypes.Where(i => !i.IsDeleted), "Id", "Name", null).OrderBy(d => d.Text);
            ViewBag.Message = this.TempData["Message"];
            ViewBag.CurrentPage = "guidePage";
            ViewBag.StringToSearch = stringToSearch;
            ViewBag.DeviceId = deviceId;
            if(deviceId != 0)
            {
                ViewBag.DeviceName = ORMdb.Devices.Find(deviceId).Name;
            }
            
            ViewBag.ManufacturerId = manufacturerId;
            if(manufacturerId != 0)
            {
                ViewBag.ManufacturerName = ORMdb.Manufacturers.Find(manufacturerId).Name;
            }
            ViewBag.ModelId = modelId;
            if (modelId != 0)
            {
                ViewBag.ModelName = ORMdb.Models.Find(modelId).Name;
            }
            ViewBag.GuideTypeId = guideTypeId;
            if(guideTypeId != 0)
            {
                ViewBag.GuideTypeName = ORMdb.GuideTypes.Find(guideTypeId).Name;
            }
            return View(guideList);
        }
        public ActionResult GetGuideList(string condition, int pageNo = 1, int deviceId = 0, int manufacturerId = 0, int modelId = 0, string stringToSearch = "", int guideTypeId = 0)
        {
            GuideListViewModel vm = null;
            List<Guide> GuideList = new List<Guide>();
            var pageInfo = new PageInfo(Convert.ToInt16(ConfigurationManager.AppSettings["GuidesPageSize"]), pageNo);
            if (condition == "new")
            {
                var feedback = _iGuideRepository.GetAllGuide(pageInfo, deviceId, manufacturerId, modelId, stringToSearch, guideTypeId);
                if (feedback.Success)
                {
                    vm = new GuideListViewModel
                    {
                        Guides = feedback.Guides,
                        PageNo = pageNo,
                        Condition = "new",
                        DeviceId = deviceId,
                        ManufacturerId = manufacturerId,
                        ModelId = modelId,
                        GuideSearch = stringToSearch,
                        TotalPage = Convert.ToInt16(Math.Ceiling((double)feedback.Total / pageInfo.PageSize)),
                    };
                    ViewBag.CurrentPage = "GuidePage";
                    return PartialView("GuideList", vm);
                }
            }

            else if (condition == "useful")
            {
                var feedback = _iGuideRepository.GetGuideUseful(pageInfo, deviceId, manufacturerId, modelId, stringToSearch, guideTypeId);
                if (feedback.Success)
                {
                    vm = new GuideListViewModel
                    {
                        Guides = feedback.Guides,
                        PageNo = pageNo,
                        Condition = "useful",
                        DeviceId = deviceId,
                        ManufacturerId = manufacturerId,
                        ModelId = modelId,
                        GuideSearch = stringToSearch,
                        TotalPage = Convert.ToInt16(Math.Ceiling((double)feedback.Total / pageInfo.PageSize)),
                    };
                    ViewBag.CurrentPage = "GuidePage";
                    return PartialView("GuideList", vm);
                }
            }

            return PartialView("GuideList");
        }

        [PermissionAuthorize]
        public ActionResult Create(int modelId = 0)
        {
            if (modelId != 0)
            {
                var model = ORMdb.Models.SingleOrDefault(m => !m.IsDeleted && m.Id == modelId);
                if (model != null)
                {
                    var guide = new Guide
                    {
                        ModelID = modelId
                    };
                    var Device_Models = from m in ORMdb.Models
                                        where m.ManufacturerId == model.ManufacturerId
                                        & m.DeviceId == model.DeviceId
                                        & !m.IsDeleted
                                        select new
                                        {
                                            m.Id,
                                            m.Name
                                        };
                    ViewData["Device_Name"] = new SelectList(ORMdb.Devices.Where(i => !i.IsDeleted), "Id", "Name", model.DeviceId).OrderBy(d => d.Text);
                    ViewData["Manufacturer_Name"] = new SelectList(ORMdb.Manufacturers.Where(i => !i.IsDeleted), "Id", "Name", model.ManufacturerId).OrderBy(m => m.Text);
                    ViewData["Model_Name"] = new SelectList(Device_Models.ToList(), "Id", "Name", guide.Model).OrderBy(m => m.Text);
                    @ViewBag.GuideType = new SelectList(ORMdb.GuideTypes.Where(i => !i.IsDeleted), "Id", "Name", guide.GuideTypeId).OrderBy(m => m.Text);
                    return View(guide);
                }
            }
            ViewData["Device_Name"] = new SelectList(ORMdb.Devices.Where(i => !i.IsDeleted), "Id", "Name", null).OrderBy(d => d.Text);
            ViewData["Manufacturer_Name"] = new SelectList(ORMdb.Manufacturers.Where(i => !i.IsDeleted), "Id", "Name", null).OrderBy(m => m.Text);
            @ViewBag.GuideType = new SelectList(ORMdb.GuideTypes.Where(i => !i.IsDeleted), "Id", "Name", null).OrderBy(m => m.Text);
            return View();
        }
        [HttpPost]
        public ActionResult Create(Guide guide)
        {
            if (ModelState.IsValid)
            {

                guide.PostedBy = CurrentUser.UserInfo.Id;
                guide.ContentHtml = guide.ContentHtml.GetSafeHtml(Constants.AllowedHtmlTags, Constants.AllowedHtmlAttributes);
                var feedback = _iGuideRepository.InsertGuide(guide);
                this.TempData["Message"] = "Bài viết của bạn đã được gửi để chờ kiểm duyệt!";
                return RedirectToAction("Index");
            }
            if(guide.ModelID != null && guide.ModelID != 0)
            {
                Model model = ORMdb.Models.Find(guide.ModelID);
                var Device_Models = from m in ORMdb.Models
                                    where m.ManufacturerId == model.ManufacturerId
                                    & m.DeviceId == model.DeviceId
                                    & !m.IsDeleted
                                    select new
                                    {
                                        m.Id,
                                        m.Name
                                    };
                ViewData["Device_Name"] = new SelectList(ORMdb.Devices.Where(i => !i.IsDeleted), "Id", "Name", model.DeviceId).OrderBy(d => d.Text);
                ViewData["Manufacturer_Name"] = new SelectList(ORMdb.Manufacturers.Where(i => !i.IsDeleted), "Id", "Name", model.ManufacturerId).OrderBy(m => m.Text);
                ViewData["Model_Name"] = new SelectList(Device_Models.ToList(), "Id", "Name", guide.Model).OrderBy(m => m.Text);
            }
            @ViewBag.GuideType = new SelectList(ORMdb.GuideTypes.Where(i => !i.IsDeleted), "Id", "Name", guide.GuideTypeId).OrderBy(m => m.Text);
            ViewBag.CurrentPage = "guidePage";
            return View(guide);
        }
        // GET: /Guide/Details/5

        public ViewResult Details(int id)
        {
            var guide = ORMdb.Guides.SingleOrDefault(g => g.Id == id && !g.IsDeleted);
            if (guide != null)
            {
                guide.Views++;
                try
                {
                    ORMdb.SaveChanges();
                }
                catch(Exception e)
                {}
                
                int currentUserId = CurrentUser == null ? 0 : Convert.ToInt16(CurrentUser.UserInfo.Id);
                var guideVote = ORMdb.VotedGuides.SingleOrDefault(t => t.GuideId == id && t.VotedById == currentUserId);
                bool isVotedByCurrentUser = guideVote != null;
                var guideReport = ORMdb.ReportedGuides.SingleOrDefault(t => t.GuideId == id && t.ReportedById == currentUserId);
                bool isReportdByCurrentUser = guideReport != null;
                var guideBookmark = ORMdb.GuideBookmarks.SingleOrDefault(t => t.GuideId == id && t.BookmarkById == currentUserId);
                bool isAddedBookmarkByCurrentUser = guideBookmark != null;

                guide.IsVotedByCurrentUser = isVotedByCurrentUser;
                guide.IsReportedByCurrentUser = isReportdByCurrentUser;
                guide.IsAddedBookmarkByCurrentUser = isAddedBookmarkByCurrentUser;
                if (guide.LastUpdate != null)
                {
                    ViewBag.UpdatedByName = ORMdb.Users.Find(guide.UpdatedBy).Username;
                }

                ViewBag.CurrentUserId = CurrentUser == null ? 0 : CurrentUser.UserInfo.Id;
                ViewBag.CurrentPage = "guidePage";
                ViewBag.BookmarkTotal = ORMdb.GuideBookmarks.Count(b => b.GuideId == id);
                ViewBag.NumberOfGuides = ORMdb.Guides.Count(g => !g.IsDeleted && g.isApproved && g.ModelID == guide.ModelID);
                ViewBag.NumberOfQuestions = ORMdb.Questions.Count(g => !g.IsDeleted && g.ModelId == guide.ModelID);
                GuideDetailsViewModel vm = new GuideDetailsViewModel();
                vm.Guide = guide;
                vm.TopOlderGuides =
                    ORMdb.Guides.Where(g => g.PostedDate < guide.PostedDate).OrderByDescending(g => g.PostedDate).Take(10).ToList();
                return View(vm);
            }
            return View();
        }

        //
        // GET: /Guide/Edit/5
        [PermissionAuthorize]
        public ActionResult Edit(int id)
        {
            Guide guide = ORMdb.Guides.Find(id);
            if (CurrentUser.UserInfo.Id != guide.PostedBy && !CurrentUser.IsInRole("Admin"))
                return View("CannotAccess");
            Model model = ORMdb.Models.Find(guide.ModelID);
            var Device_Models = from m in ORMdb.Models
                                where m.ManufacturerId == model.ManufacturerId
                                & m.DeviceId == model.DeviceId
                                & !m.IsDeleted
                                select new
                                {
                                    m.Id,
                                    m.Name
                                };
            ViewData["Device_Name"] = new SelectList(ORMdb.Devices.Where(i => !i.IsDeleted), "Id", "Name", model.DeviceId).OrderBy(d => d.Text);
            ViewData["Manufacturer_Name"] = new SelectList(ORMdb.Manufacturers.Where(i => !i.IsDeleted), "Id", "Name", model.ManufacturerId).OrderBy(m => m.Text);
            ViewData["Model_Name"] = new SelectList(Device_Models.ToList(), "Id", "Name", guide.Model).OrderBy(m => m.Text);



            @ViewBag.GuideType = new SelectList(ORMdb.GuideTypes.Where(i => !i.IsDeleted), "Id", "Name", guide.GuideTypeId).OrderBy(m => m.Text);
            ViewBag.CurrentPage = "guidePage";

            return View(guide);
        }

        //
        // POST: /Guide/Edit/5

        [HttpPost]
        public ActionResult Edit(Guide guide)
        {
            if (ModelState.IsValid)
            {
                int currentUserId = CurrentUser == null ? 0 : Convert.ToInt16(CurrentUser.UserInfo.Id);
                guide.UpdatedBy = currentUserId;
                var feedback = _iGuideRepository.UpdateGuide(guide);

                //ORMdb.Entry(guide).State = EntityState.Modified;
                //ORMdb.SaveChanges();
                return RedirectToAction("Details", new { id = guide.Id });
            }
            Model model = ORMdb.Models.Find(guide.ModelID);
            var Device_Models = from m in ORMdb.Models
                                where m.ManufacturerId == model.ManufacturerId
                                & m.DeviceId == model.DeviceId
                                & !m.IsDeleted
                                select new
                                {
                                    m.Id,
                                    m.Name
                                };
            ViewData["Device_Name"] = new SelectList(ORMdb.Devices.Where(i => !i.IsDeleted), "Id", "Name", model.DeviceId).OrderBy(d => d.Text);
            ViewData["Manufacturer_Name"] = new SelectList(ORMdb.Manufacturers.Where(i => !i.IsDeleted), "Id", "Name", model.ManufacturerId).OrderBy(m => m.Text);
            ViewData["Model_Name"] = new SelectList(Device_Models.ToList(), "Id", "Name", guide.Model).OrderBy(m => m.Text);



            @ViewBag.GuideType = new SelectList(ORMdb.GuideTypes.Where(i => !i.IsDeleted), "Id", "Name", guide.GuideTypeId).OrderBy(m => m.Text);
            ViewBag.CurrentPage = "guidePage";
            return View(guide);
        }

        [PermissionAuthorize]
        public ActionResult EditComment(int id)
        {
            GuideComment comment = ORMdb.GuideComments.Find(id);
            ViewBag.CurrentPage = "guidePage";

            return View(comment);
        }

        //
        // POST: /GuideComment/Edit/5

        [HttpPost]
        public ActionResult EditComment(GuideComment comment)
        {
            if (ModelState.IsValid)
            {
                // Guide guide = new Guide();
                var feedback = _iGuideRepository.UpdateGuideComment(comment);

                //   guide = ORMdb.Guides.SingleOrDefault(i => i.Id == comment.GuideId);

                return RedirectToAction("Details", new { id = comment.GuideId });

                //return RedirectToAction("Index");
            }
            // ViewBag.PostedById = new SelectList(ORMdb.Users, "Id", "Username", Guide.PostedById);
            // ViewBag.UpdatedById = new SelectList(ORMdb.Users, "Id", "Username", Guide.UpdatedById);
            return View(comment);
        }

        [PermissionAuthorize]
        public string Delete(int id)
        {
            try
            {
                Guide guide = ORMdb.Guides.Find(id);
                guide.IsDeleted = true;
                ORMdb.SaveChanges();
                return "";
            }
            catch (Exception e)
            {
                return "Da co loi xay ra";
            }
        }

        //
        // POST: /Guide/Delete/5

        //[HttpPost, ActionName("Delete")]
        //public ActionResult DeleteConfirmed(int id)
        //{
        //    Guide guide = ORMdb.Guides.Find(id);
        //    var feedback = _iGuideRepository.DeleteGuide(id);
        //    //ORMdb.Guides.Remove(guide);
        //    //ORMdb.SaveChanges();
        //    return RedirectToAction("Index");
        //}
        public ActionResult ManufacturerNameChange(int Manufacturer_Id, int Device_Id)
        {
            var Device_Models = from m in ORMdb.Models
                                where m.ManufacturerId == Manufacturer_Id
                                & m.DeviceId == Device_Id
                                & !m.IsDeleted
                                orderby m.Name
                                select new
                                {
                                    m.Id,
                                    m.Name
                                };
            return Json(Device_Models.ToList(), JsonRequestBehavior.AllowGet);
        }
        public ActionResult DeviceNameChange(int Manufacturer_Id, int Device_Id)
        {
            var Device_Models = from m in ORMdb.Models
                                where m.ManufacturerId == Manufacturer_Id
                                & m.DeviceId == Device_Id
                                & !m.IsDeleted
                                orderby m.Name
                                select new
                                {
                                    m.Id,
                                    m.Name
                                };
            return Json(Device_Models.ToList(), JsonRequestBehavior.AllowGet);
        }
        public ActionResult UpdateManufacturerList(int Device_Id)
        {
            var queryString = "select distinct mf.* from Manufacturers as mf inner join Models as m on mf.Id = m.ManufacturerId where m.DeviceId = {0} and mf.IsDeleted = 'false'";
            var Manufacturers = (ORMdb as System.Data.Entity.Infrastructure.IObjectContextAdapter)
                              .ObjectContext.ExecuteStoreQuery<Manufacturer>(queryString, Device_Id).ToList();
            return Json(Manufacturers.ToList(), JsonRequestBehavior.AllowGet);
        }
        //Get comment list
        public ActionResult GetCommentList(int guideId, string condition, int pageNo = 1)
        {
            CommentListViewModel vm = null;
            List<GuideComment> commentist = new List<GuideComment>();
            int currentUserId = CurrentUser == null ? 0 : Convert.ToInt16(CurrentUser.UserInfo.Id);
            var pageInfo = new PageInfo(Convert.ToInt16(ConfigurationManager.AppSettings["AnswersPageSize"]), pageNo);
            if (condition == "new")
            {
                var feedback = _iCommentRepository.GetAllComments(currentUserId, guideId, pageInfo);
                if (feedback.Success)
                {
                    vm = new CommentListViewModel
                    {
                        Comments = feedback.Comments,
                        GuideId = guideId,
                        PageNo = pageNo,
                        CurrentUserId = CurrentUser == null ? 0 : Convert.ToInt16(CurrentUser.UserInfo.Id),
                        Condition = "new",
                        TotalPage = Convert.ToInt16(Math.Ceiling((double)feedback.Total / pageInfo.PageSize))

                    };
                    ViewBag.NumberOfCommentOnPage = vm.Comments.Count;
                    return PartialView("CommentList", vm);
                }

            }

            else if (condition == "highScore")
            {
                var feedback = _iCommentRepository.GetHighScoreComments(currentUserId, guideId, pageInfo);
                if (feedback.Success)
                {
                    vm = new CommentListViewModel
                    {
                        Comments = feedback.Comments,
                        GuideId = guideId,
                        PageNo = pageNo,
                        CurrentUserId = CurrentUser == null ? 0 : Convert.ToInt16(CurrentUser.UserInfo.Id),
                        Condition = "highScore",
                        TotalPage = Convert.ToInt16(Math.Ceiling((double)feedback.Total / pageInfo.PageSize)),
                    };
                    return PartialView("CommentList", vm);
                }

            }
            return PartialView("CommentList");
        }





        //Submit New Comment
        [HttpPost]
        public String SubmitGuideComment(GuideComment Comment)
        {
            if (CurrentUser == null)
                return Resources.Messages.NeedLogin;

            List<GuideComment> commentList = new List<GuideComment>();
            if (ModelState.IsValid)
            {

                Comment.PostedBy = CurrentUser.UserInfo.Id;

                // Call Repository to perform insert
                var feedback = _iCommentRepository.InsertComment(Comment);
                if (feedback.Success)
                {
                    commentList.Add(feedback.Data);
                    return "True";
                }
            }
            return "Đã Có Lỗi Xảy Ra!";
        }
        //Vote for an Guide
        [HttpPost]
        public JsonResult PlusPointForAnGuide(int GuideId)
        {
            if (CurrentUser == null)
                return Json(new { message = Resources.Messages.NeedLogin, newPoint = "" });

            var feedback = _iGuideRepository.VoteGuide(GuideId, CurrentUser.UserInfo.Id);
            if (feedback.Success)
            {
                return Json(new { message = "", newPoint = feedback.Data.UpVotes });
            }
            return Json(new { message = feedback.Message, newPoint = "" });
        }
        public ActionResult GetGuideBookmarksList(int pageNo = 1)
        {
            GuideBookmarkListViewModel vm = null;
            List<Guide> guideList = new List<Guide>();
            int currentUserId = CurrentUser == null ? 0 : Convert.ToInt16(CurrentUser.UserInfo.Id);
            var pageInfo = new PageInfo(Convert.ToInt16(ConfigurationManager.AppSettings["QuestionBookmarksPageSize"]), pageNo);
            var feedback = _iGuideRepository.GetGuideBookmarks(currentUserId, pageInfo);
            if (feedback.Success)
            {
                vm = new GuideBookmarkListViewModel()
                {
                    Guides = feedback.Guides,
                    CurrentUserId = currentUserId,
                    PageNo = pageNo,
                    TotalPage = Convert.ToInt16(Math.Ceiling((double)feedback.Total / pageInfo.PageSize))

                };
                return PartialView("GuideBookmarksList", vm);
            }

            return PartialView("GuideBookmarksList");
        }
        [PermissionAuthorize]
        [HttpPost]
        public JsonResult AddBookmarkAnGuide(int GuideId)
        {
            if (CurrentUser == null)
                return Json(new { message = Resources.Messages.NeedLogin });
            var feedback = _iGuideRepository.AddBookmarkAnGuide(GuideId, CurrentUser.UserInfo.Id);
            if (feedback.Success)
            {
                return Json(new { message = "", newBookmark = ORMdb.GuideBookmarks.Count(b => b.GuideId == feedback.Data.Id) });
            }
            return Json(new { message = feedback.Message, newBookmark = "" });
        }

        //vote for an Comment
        [PermissionAuthorize]
        [HttpPost]
        public JsonResult PlusPointForAnComment(int CommentId)
        {
            if (CurrentUser == null)
                return Json(new { message = Resources.Messages.NeedLogin, newPoint = "" });
            var feedback = _iCommentRepository.VoteComment(CommentId, CurrentUser.UserInfo.Id);
            if (feedback.Success)
            {
                return Json(new { message = "", newPoint = feedback.Data.UpVotes });
            }
            return Json(new { message = feedback.Message, newPoint = "" });
        }

        //Accept An Comment
        [PermissionAuthorize]
        [HttpPost]
        public string DeleteAnComment(int GuideId, int CommentId)
        {
            var feedback1 = _iGuideRepository.DeleteAnComment(GuideId);
            var feedback2 = _iCommentRepository.DeleteAnComment(CommentId);
            if (feedback1.Success && feedback2.Success)
            {
                return "true";
                //return RedirectToAction("Details", new { id == GuideId });
            }
            return "false";
        }


        //Report for an Guide
        [PermissionAuthorize]
        [HttpPost]
        public JsonResult ReportAnGuide(int GuideId, string Reason)
        {
            if (CurrentUser == null)
                return Json(new { message = Resources.Messages.NeedLogin });
            var feedback = _iGuideRepository.ReportGuide(GuideId, Reason, CurrentUser.UserInfo.Id);
            if (feedback.Success)
            {
                return Json(new { message = "" });
            }
            return Json(new { message = feedback.Message });
        }
        [PermissionAuthorize]
        [HttpPost]
        public JsonResult ReportAnComment(int CommentId, string Reason)
        {
            if (CurrentUser == null)
                return Json(new { message = Resources.Messages.NeedLogin });
            var feedback = _iCommentRepository.ReportComment(CommentId, Reason, CurrentUser.UserInfo.Id);
            if (feedback.Success)
            {
                return Json(new { message = "" });
            }
            return Json(new { message = feedback.Message });
        }
        protected override void Dispose(bool disposing)
        {
            ORMdb.Dispose();
            base.Dispose(disposing);
        }



    }
}
